//
//  ViewController.m
//  GCD的使用
//
//  Created by 伍银荣 on 2021/8/26.
//  Copyright © 2021 com.WYR. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
   // [self demo8];
//    NSLog(@"start");
//    //GCD的其他操作
//    //延迟处理
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"延迟2秒后执行");
//    });
//    NSLog(@"end");
    
    //一次性执行:在当前线程上执行
    //一次执行的原理:判断静态的全局变量的值,默认是0,如果执行完成后,会变成-1
    //dispatch_once内部会判断变量的值,如果是0的话才执行
//    static dispatch_once_t onceToken;
//    NSLog(@"%zd",onceToken);
//    dispatch_once(&onceToken, ^{
//        NSLog(@"hello - %@",[NSThread currentThread]);
//    });
//    NSLog(@"%zd",onceToken);
//    for (int i = 0; i < 5; i++) {
//        Person *p = [Person sharedPerson];
//        NSLog(@"%p",p); //得到的都是同一个地址的对象
//    }
//
//    Person *p1 = [Person sharedPersonWithOnce];
//    NSLog(@"p1 = %p",p1);
    
//    [self demo9];
//    [self demo10];
    
    
    [self demo11];
}

//同步执行 串行队列----没有新线程产生,顺序执行
- (void)demo1 {
    //创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 10; i++) {
        //同步执行任务
        dispatch_sync(queue, ^{
            NSLog(@"hello----%d----%@",i,[NSThread currentThread]);
        });
    }
}

//同步执行 并行队列----没有产生信线程,顺序执行
- (void)demo2 {
    //创建并行队列
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        //同步执行任务
        dispatch_sync(queue, ^{
            NSLog(@"hello---%d--%@",i,[NSThread currentThread]);
        });
    }
}

//异步执行任务, 串行队列----产生了一个新的线程,顺序执行
- (void)demo3 {
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"hello---%d--%@",i, [NSThread currentThread]);
        });
    }
}

//异步执行, 并发队列----产生了多个线程,无序执行
- (void)demo4 {
    //创建并行队列
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        //创建异步任务
        dispatch_async(queue, ^{
            NSLog(@"hello---%d---%@",i, [NSThread currentThread]);
        });
    }
}

//同步执行,全局队列----不产生新线程,顺序执行
- (void)demo5 {
    //创建全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    for (int i = 0; i < 10; i++) {
        //创建同步任务
        dispatch_sync(queue, ^{
            NSLog(@"hello---%d---%@",i, [NSThread currentThread]);
        });
    }
}

//异步执行任务,全局队列---等同于异步执行,并发队列    产生了多个线程,无序执行
- (void)demo6 {
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"hello--%d--%@",i, [NSThread currentThread]);
        });
    }
}

//主队列的特点:如果主线程正在执行代码,就不调度任务
//同步执行:如果第一个任务没有执行,就继续等待第一个任务执行完成,再执行下一个任务,此时相互等等待,程序无法向下执行,就发生了死锁
//同步执行任务, 主队列---运行在主线程上,会发生死锁

- (void)demo7 {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"hello--%@",[NSThread currentThread]);
    });
}


//异步执行任务,主队列----没有产生新线程,顺序执行
- (void)demo8 {
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"hello--%d--%@",i, [NSThread currentThread]);
        });
    }
}

//获取加锁创建的时间
- (void)demo9 {
    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    for (int i = 0 ; i < 100000; i++) {
        [Person sharedPerson];
       // NSLog(@"%p",p); //得到的都是同一个地址的对象
    }
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"加锁时间:%f",end - start);
}

//使用once后的时间间隔:相比加锁产生的时间间隔少了很多
- (void)demo10 {
    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    for (int i = 0; i < 100000; i++) {
        [Person sharedPersonWithOnce];
    }
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"once的时间间隔:%f",end - start);
}


//使用调度组在多个异步任务都执行完成后,继续做某件事情. 比如下载歌曲,等所有歌曲下载完毕后,再到主线程去通知提示用户
- (void)demo11 {
    //全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    //创建调度组
    dispatch_group_t group = dispatch_group_create();
    //吧任务添加到队列中,等任务执行完成后通知调度组
    dispatch_group_async(group, queue, ^{
        NSLog(@"歌曲1: %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"歌曲2: %@",[NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"歌曲3: %@",[NSThread currentThread]);
    });
    //等到三首歌曲都下载完成后再回到主线程通知
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //更新UI控件,提示用户
        NSLog(@"OK-%@",[NSThread currentThread]);
    });
    //等待调度组,监听的队列中的所有任务执行完毕,才会执行后续代码,会阻塞线程,很少使用
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"end");
}


@end
